﻿using System;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

namespace Ellanet
{
    public partial class Guest : Form // KryptonForm
    {
        private string _guiXmlPath = null;
        private string _vmxPath = null;
        private string _hostName = null;
        private string _vmrunPath = null;
        private BackgroundWorker listGuestThread;
        private ArrayList guests;
        private bool listVMReturn = false;
        private ErrorProvider ep = new ErrorProvider();

        delegate string GetComboBoxTextPropertyDelegate(ref ComboBox cb);
        delegate void AddItemToComboBoxDelegate(ref ComboBox cb, string item);

        public Guest(string vmxPath, string hostName, string guiXmlPath, string vmrunPath)
        {
            InitializeComponent();
            _guiXmlPath = guiXmlPath;
            _vmxPath = vmxPath;
            _hostName = hostName;
            _vmrunPath = vmrunPath;
            this.Load += new EventHandler(AddGuest_Load);
            addButton.Click += new EventHandler(addButton_Click);
            hostComboBox.SelectedIndexChanged += new EventHandler(hostComboBox_SelectedIndexChanged);
            vmxComboBox.SelectedIndexChanged += new EventHandler(vmxComboBox_SelectedIndexChanged);
            browseButton.Click += new EventHandler(browseButton_Click);
            newCredentialsButton.Click += new EventHandler(newCredentialsButton_Click);
        }

        void newCredentialsButton_Click(object sender, EventArgs e)
        {
            Credentials cred = new Credentials(null, _guiXmlPath);

            if (cred.ShowDialog() == DialogResult.OK)
            {
                UpdateCredentialsList();
                credentialsComboBox.Text = cred.CredentialsName;
            }
        }

        void browseButton_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.CheckFileExists = true;
            ofd.CheckPathExists = true;
            ofd.DefaultExt = "vmx";
            ofd.Filter = "VMware Virtual Machine|*.vmx";
            ofd.Multiselect = false;

            if (ofd.ShowDialog() == DialogResult.OK)
            {
                vmxComboBox.Text = ofd.FileName;
                AutoGuessGuestName();
            }
        }

        void vmxComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            AutoGuessGuestName();
        }

        void AutoGuessGuestName()
        {
            if ((nameTextBox.Text == null) || (nameTextBox.Text.Trim().Length == 0))
            {
                if (vmxComboBox.Text.EndsWith(".vmx"))
                {
                    nameTextBox.Text = vmxComboBox.Text.Substring(vmxComboBox.Text.LastIndexOfAny(new char[] { Convert.ToChar("\\"), Convert.ToChar("/") }) + 1).Replace(".vmx", String.Empty);
                    descriptionComboBox.Select();
                }
            }
        }

        void hostComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (listGuestThread != null)
            {
                listGuestThread.CancelAsync();
            }

            listGuestThread = new BackgroundWorker();
            listGuestThread.DoWork += new DoWorkEventHandler(listGuestThread_DoWork);
            listGuestThread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(listGuestThread_RunWorkerCompleted);
            listGuestThread.WorkerSupportsCancellation = true;
            listGuestThread.RunWorkerAsync();
            vmxComboBox.Items.Clear();
        }

        void listGuestThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (listVMReturn && (guests.Count > 1))
            {
                guests.RemoveAt(0);

                foreach (string guest in guests)
                {
                    AddItemToComboBox(ref vmxComboBox, guest);
                }
            }
        }

        void listGuestThread_DoWork(object sender, DoWorkEventArgs e)
        {
            if (guests != null)
            {
                guests.Clear();
            }

            string username = null;
            string password = null;
            int exitCode;
            vmrunGUIXmlWrapper guiXmlWrapper = new vmrunGUIXmlWrapper(_guiXmlPath);
            guiXmlWrapper.GetCredentials(guiXmlWrapper.GetHostChildNodeInnerText(GetComboBoxTextProperty(ref hostComboBox), "credentials"), out username, out password);
            listVMReturn = new vmrunCLIWrapper(_vmrunPath, guiXmlWrapper.GetHostChildNodeInnerText(GetComboBoxTextProperty(ref hostComboBox), "type"), guiXmlWrapper.GetHostChildNodeInnerText(GetComboBoxTextProperty(ref hostComboBox), "arguments"), username, password, null, null, "listRegisteredVM").ExecuteCommand(30, out guests, out exitCode);

            if (!listVMReturn)
            {
                listVMReturn = new vmrunCLIWrapper(_vmrunPath, guiXmlWrapper.GetHostChildNodeInnerText(GetComboBoxTextProperty(ref hostComboBox), "type"), guiXmlWrapper.GetHostChildNodeInnerText(GetComboBoxTextProperty(ref hostComboBox), "arguments"), username, password, null, null, "list").ExecuteCommand(30, out guests, out exitCode);
            }
        }

        void addButton_Click(object sender, EventArgs e)
        {
            if (ValidateForm())
            {
                vmrunGUIXmlWrapper guiXmlWrapper = new vmrunGUIXmlWrapper(_guiXmlPath);

                if (_hostName != null)
                {
                    guiXmlWrapper.RemoveGuest(_vmxPath, _hostName);
                }

                guiXmlWrapper.AddGuest(nameTextBox.Text.Trim(), hostComboBox.Text, vmxComboBox.Text.Trim(), descriptionComboBox.Text.Trim(), credentialsComboBox.Text);
                guiXmlWrapper.SaveXml();
                this.DialogResult = DialogResult.OK;
                this.Close();
            }
        }

        void AddGuest_Load(object sender, EventArgs e)
        {
            UpdateCredentialsList();
            UpdateOSList();

            foreach (string host in new vmrunGUIXmlWrapper(_guiXmlPath).GetHostNames())
            {
                hostComboBox.Items.Add(host);
            }

            if (_hostName != null)
            {
                vmrunGUIXmlWrapper guiXmlWrapper = new vmrunGUIXmlWrapper(_guiXmlPath);
                hostComboBox.Text = _hostName;
                vmxComboBox.Text = _vmxPath;
                nameTextBox.Text = guiXmlWrapper.GetGuestChildNodeInnerText(_vmxPath, _hostName, "name");
                descriptionComboBox.Text = guiXmlWrapper.GetGuestChildNodeInnerText(_vmxPath, _hostName, "description");
                credentialsComboBox.Text = guiXmlWrapper.GetGuestChildNodeInnerText(_vmxPath, _hostName, "credentials");
            }
            else
            {
                if (hostComboBox.Items.Count == 1)
                {
                    hostComboBox.SelectedIndex = 0;
                }
            }
        }

        bool ValidateForm()
        {
            ep.Dispose();

            if (hostComboBox.SelectedIndex == -1)
            {
                ep.SetError(hostComboBox, "Please specify which Host the Guest is associated with.");
                hostComboBox.Select();
                return false;
            }

            if (((vmxComboBox.Text == null) || (vmxComboBox.Text.Trim().Length == 0)) || ((((_vmxPath == null) || (_vmxPath != vmxComboBox.Text)) || ((_hostName == null) || (_hostName != hostComboBox.Text))) && (new vmrunGUIXmlWrapper(_guiXmlPath).GuestExists(vmxComboBox.Text, hostComboBox.Text))))
            {
                ep.SetError(vmxComboBox, "Please specify a unique VMX path.");
                vmxComboBox.Select();
                return false;
            }

            if (!vmxComboBox.Text.Trim().ToLower().EndsWith(".vmx"))
            {
                ep.SetError(vmxComboBox, "This path must end with .vmx.");
                vmxComboBox.Select();
                return false;
            }

            if ((nameTextBox.Text == null) || (nameTextBox.Text.Trim().Length == 0))
            {
                ep.SetError(nameTextBox, "Please specify a name for this Guest.");
                nameTextBox.Select();
                return false;
            }

            if (credentialsComboBox.SelectedIndex == -1)
            {
                ep.SetError(credentialsComboBox, "Please specify the Guest Credentials that should be used when managing the Guests operating system.");
                credentialsComboBox.Select();
                return false;
            }

            return true;
        }

        private string GetComboBoxTextProperty(ref ComboBox cb)
        {
            if (InvokeRequired)
            {
                return Convert.ToString(Invoke(new GetComboBoxTextPropertyDelegate(GetComboBoxTextProperty), new object[] { cb }));
            }
            else
            {
                return cb.Text;
            }
        }

        void AddItemToComboBox(ref ComboBox cb, string item)
        {
            if (InvokeRequired)
            {
                Invoke(new AddItemToComboBoxDelegate(AddItemToComboBox), new object[] { cb, item });
            }
            else
            {
                cb.Items.Add(item);
            }
        }

        void UpdateCredentialsList()
        {
            credentialsComboBox.Items.Clear();

            foreach (string credentials in new vmrunGUIXmlWrapper(_guiXmlPath).GetCredentialsNames())
            {
                credentialsComboBox.Items.Add(credentials);
            }
        }

        void UpdateOSList()
        {
            descriptionComboBox.Items.Clear();

            foreach (string os in new vmrunInfoXmlWrapper().GetSuggestedOSs())
            {
                descriptionComboBox.Items.Add(os);
            }
        }
    }
}
